﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Threading;
using WorldBankBBS.Data;
using WorldBankBBS.Handlers;
using WorldBankBBS.Input;
using WorldBankBBS.Logic;
using WorldBankBBS.Menus;
using WorldBankBBS.Pathing;
using WorldBankBBS.RichEditor;
using WorldBankBBS.Translators;
using WorldBankBBS.Translators.PetsciiEncoder;
using Session = WorldBankBBS.Logic.Session;

namespace WorldBankBBS.Subboards
{
    public class SubboardsHandler
    {
        private static event TextInputHandler TextInput;

        internal static List<Message> ListMessages(Session session, bool display = true, bool unreadOnly = false)
        {
            var builder = new List<byte>();
            var translator = session.Encoding.GetTranslator(session);
            var list = new List<Message>();
            var buffer = new byte[1024];
            var l = 0;
            if (display)
            {
                l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_LIST_TOP);
                for (int i = 0; i < l; ++i)
                    builder.Add(buffer[i]);
            }

            using (var mh = new ModelHelper())
            {
                mh.BeginNewContext();

                if (session.ContainsProperty("CurrentThreadUID"))
                {
                    var threadUID = Guid.Empty;
                    var count = 1;
                    var unread = 0;

                    if (Guid.TryParse(Convert.ToString(session["CurrentThreadUID"]), out threadUID))
                    {
                        list =
                            mh.Context.Messages.Where(x => x.Thread.ThreadUID == threadUID && !x.IsDeleted)
                                .OrderBy(x => x.Timestamp)
                                .ToList();

                        if (display)
                        {
                            foreach (var message in list)
                            {
                                var messageUser = message.MessageUsers.FirstOrDefault(
                                    mu => mu.UserUID == session.User.UserUID);

                                if (messageUser == null)
                                {
                                    messageUser =
                                        new MessageUser
                                        {
                                            MessageUID = message.MessageUID,
                                            UserUID = session.User.UserUID
                                        };
                                    mh.Context.MessageUsers.Add(messageUser);
                                    mh.Context.SaveChanges();
                                }

                                var isRead = messageUser.IsRead;

                                if (!isRead) ++unread;

                                if (!unreadOnly || !isRead)
                                {
                                    l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_LIST_ITEM, count++,
                                        message.Timestamp.ToLocalTime().ToString("yyyy-MM-dd hh:mm tt"), message.User.UserName,
                                        message.Subject, isRead ? "" : "new");
                                    for (int i = 0; i < l; ++i)
                                        builder.Add(buffer[i]);
                                }
                                else
                                {
                                    ++count;
                                }
                            }

                            l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_LIST_BOT, count - 1, unread);
                            for (int i = 0; i < l; ++i)
                                builder.Add(buffer[i]);

                            var pages = Paginator.Paginate(builder.ToArray(), 0, builder.Count, 24, session.Encoding);

                            for (int p = 0; p < pages.Count; ++p)
                            {
                                session.Connection.SendData(pages[p]);
                                if (p != pages.Count - 1)
                                    session.InvokePause(session.Encoding);
                            }
                        }
                    }
                }
            }

            return list;
        }

        public static void OnListMessages(object sender, Session session)
        {
            ListMessages(session, true);
        }

        public static void OnListUnreadMessages(object sender, Session session)
        {
            ListMessages(session, true, true);
        }

        public static void OnListSubboards(object sender, Session session)
        {
            ListSubboards(session, true);
        }

        internal static List<Subboard> ListSubboards(Session session, bool display = true)
        {
            var builder = new List<byte>();
            var list = new List<Subboard>();
            var translator = session.Encoding.GetTranslator(session);
            var buffer = new byte[1024];
            var l = 0;
            var count = 1;
            var unread = 0;
            if (display)
            {
                l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_TOP);
                for (int i = 0; i < l; ++i)
                    builder.Add(buffer[i]);
            }

            using (var mh = new ModelHelper())
            {
                mh.BeginNewContext();

                var subs = mh.Context.Subboards.OrderBy(x => x.Sig.DisplayOrder).ThenBy(x => x.DisplayOrder).ToList();
                foreach (var sub in subs)
                {
                    // FUTURE!  Apply SIG-Level Security

                    list.Add(sub);

                    var unreadInSub = sub.GetUnreadMessagesForUser(session.User.UserUID);

                    if (display)
                    {
                        l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_ITEM, count++, unreadInSub, sub.Sig.SigName, sub.SubboardName, sub.SubboardDescription);

                        for (int i = 0; i < l; ++i)
                            builder.Add(buffer[i]);
                    }

                    unread += unreadInSub;
                }
            }

            if (display)
            {
                l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_BOT, unread);

                for (int i = 0; i < l; ++i)
                    builder.Add(buffer[i]);

                var pages = Paginator.Paginate(builder.ToArray(), 0, builder.Count, 24, session.Encoding);

                for (int p = 0; p < pages.Count; ++p)
                {
                    session.Connection.SendData(pages[p]);
                    if (p != pages.Count - 1)
                        session.InvokePause(session.Encoding);
                }
            }

            session["TotalUnreadMessages"] = unread;

            return list;
        }

        internal static List<WorldBankBBS.Data.Thread> ListThreads(Session session, bool display = true)
        {
            var builder = new List<byte>();
            var translator = session.Encoding.GetTranslator(session);
            var list = new List<WorldBankBBS.Data.Thread>();
            var buffer = new byte[1024];
            var l = 0;
            var count = 1;
            var unread = 0;
            var subboardUID = session["CurrentSubboardUID"] as Guid? ?? Guid.Empty;

            using (var mh = new ModelHelper())
            {
                mh.BeginNewContext();

                var sub = mh.Context.Subboards.FirstOrDefault(x => x.SubboardUID == subboardUID);

                if (sub != null)
                {
                    if (display)
                    {
                        l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_THREADS_TOP);
                        for (int i = 0; i < l; ++i)
                            builder.Add(buffer[i]);
                    }

                    foreach (var thread in sub.Threads.OrderBy(x => x.ThreadName))
                    {
                        list.Add(thread);

                        if (display)
                        {
                            var unreadInSub = thread.GetUnreadMessagesForUser(session.User.UserUID);

                            l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_THREAD_ITEM, count++,
                                unreadInSub, thread.ThreadName, thread.ThreadDescription);

                            for (int i = 0; i < l; ++i)
                                builder.Add(buffer[i]);

                            unread += unreadInSub;
                        }
                    }

                    if (display)
                    {
                        l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_THREADS_BOT, unread);

                        for (int i = 0; i < l; ++i)
                            builder.Add(buffer[i]);

                        var pages = Paginator.Paginate(builder.ToArray(), 0, builder.Count, 24, session.Encoding);

                        for (int p = 0; p < pages.Count; ++p)
                        {
                            session.Connection.SendData(pages[p]);
                            if (p != pages.Count - 1)
                                session.InvokePause(session.Encoding);
                        }
                    }
                }
            }


            return list;
        }

        public static void OnListThreads(object sender, Session session)
        {
            ListThreads(session, true);
        }

        public static void OnEnterMessageSection(object sender, Session session)
        {
            var menuProcessor = new MenuProcessor();
            var items = ListMessages(session, true);

            var context = new SubboardsContext() { Context = Guid.Empty.ToString() };
            session["MenuContext"] = context;

            var lookups = new Dictionary<string, Guid>();
            var count = 1;
            foreach (var l in items)
            {
                lookups.Add((count++).ToString(), l.MessageUID);
            }
            session["MenuLookups"] = lookups;

            if (!session.ContainsProperty("CurrentSubboardUID"))
                session["CurrentSubboardUID"] = Guid.Parse(ConfigurationManager.AppSettings["DefaultSubboardUID"]);

            if (!session.ContainsProperty("CurrentThreadUID"))
                session["CurrentThreadUID"] = Guid.Parse(ConfigurationManager.AppSettings["DefaultThreadUID"]);

            ListSubboards(session, false);

            if (session.ContainsProperty("TotalUnreadMessages"))
            {
                var unread = (int)session["TotalUnreadMessages"];

                var translator = session.Encoding.GetTranslator(session);
                var buffer = new byte[1024];
                var l = 0;

                l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_UNREAD, unread);
                session.Connection.SendData(buffer, 0, l, l);
            }

            menuProcessor.ProcessMenu(new SubboardsMenuProvider(), session);
        }

        public static void OnPreCreateMessage(object sender, Session session)
        {
            var handler = new TextFileHandler(session);
            handler.SendFile(session, "TextFiles\\OnPreCreateMessage");
            session.InvokePause(session.Encoding);
        }

        public static void OnCreateThread(object sender, Session session)
        {
            var translator = session.Encoding.GetTranslator(session);
            var buffer = new byte[1024];
            var l = 0;

            l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_PROMPT_THREAD);
            session.Connection.SendData(buffer, 0, l, l);

            InputHandler inputHandler = new InputHandler();
            TextInput -= inputHandler.OnTextInput;
            TextInput += inputHandler.OnTextInput;

            var thread = TextInput(session, translator, session.Connection, session.Encoding == "PETSCII" ? 30 : 70, false);

            TextInput -= inputHandler.OnTextInput;

            if (!string.IsNullOrEmpty(thread))
            {
                using (var mh = new ModelHelper())
                {
                    mh.BeginNewContext();

                    var t = new WorldBankBBS.Data.Thread
                    {
                        ThreadUID = Guid.NewGuid(),
                        SubboardUID = (Guid)session["CurrentSubboardUID"],
                        IsDeleted = false,
                        ThreadName = thread,
                        ThreadDescription = string.Empty,
                    };

                    mh.Context.Threads.Add(t);

                    mh.Context.SaveChanges();

                    session["CurrentThreadUID"] = t.ThreadUID;
                }
            }
        }

        public static void OnCreateMessage(object sender, Session session)
        {
            var translator = session.Encoding.GetTranslator(session);
            var buffer = new byte[1024*256];
            var l = 0;
            var timestamp = DateTime.UtcNow;
            var sw = (int) session["ScreenWidth"];

            if ((Guid) session["CurrentThreadUID"] == Guid.Empty)
            {
                l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_NO_THREAD);
                session.Connection.SendData(buffer, 0, l, l);
                return;
            }

            InputHandler inputHandler = new InputHandler();

            var uid = (Guid) session["ReplyToSubboardMessageUID"];
            if (uid == Guid.Empty)
            {
                l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_SUBJECT_PROMPT);
                session.Connection.SendData(buffer, 0, l, l);

                TextInput -= inputHandler.OnTextInput;
                TextInput += inputHandler.OnTextInput;

                var subject = TextInput(session, translator, session.Connection, session.Encoding == "PETSCII" ? 30 : 70,
                    false);

                TextInput -= inputHandler.OnTextInput;

                if (subject.Length > 0)
                {
                    var te = new TextEditor();

                    if (te.Initialize(session,
                        null,
                        new TextEditor.Field<DateTime>(0, 0)
                        {
                            Format = "0:g",
                            LabelText = "{YELLOW}",
                            Value = timestamp.ToLocalTime()
                        },
                        new TextEditor.Field<string>(0, 2)
                        {
                            Format = "0:-" + (sw - 10),
                            LabelText = "{PURPLE}Subject{WHITE}:{CYAN}",
                            Value = subject,
                        },
                        new TextEditor.Field<string>(0, 1)
                        {
                            Format = "0:-" + (sw - 10),
                            LabelText = "{PURPLE}Thread{WHITE}:{CYAN}",
                            Value = Data.Thread.GetFromThreadUID((Guid) session["CurrentThreadUID"]).ThreadName,
                        },
                        3, 1,
                        new TextEditor.Field<string>(0, (int) session["ScreenHeight"] - 1)
                        {
                            Format = "0:-" + (sw - 1),
                            LabelText =
                                session.Encoding == "PETSCII"
                                    ? "{WHITE}. on blank line for command menu"
                                    : "{WHITE}^{YELLOW}A {WHITE}- {CYAN}Abort{WHITE}, ^{YELLOW}S {WHITE}- {CYAN}Save{WHITE}, ^{YELLOW}Z {WHITE}- {CYAN}Undo{WHITE}, ^{YELLOW}R {WHITE}- {CYAN}Redraw{WHITE}",
                            Value = string.Empty
                        }
                        ))
                    {
                        l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_POSTED);
                        session.Connection.SendData(buffer, 0, l, l);

                        using (var mh = new ModelHelper())
                        {
                            mh.BeginNewContext();

                            var msg = new Message
                            {
                                FromUserUID = session.User.UserUID,
                                MessageUID = Guid.NewGuid(),
                                Timestamp = DateTime.UtcNow,
                                MessageBody = te.Text,
                                Subject = subject,
                                ThreadUID = (Guid) session["CurrentThreadUID"],
                            };

                            mh.Context.Messages.Add(msg);

                            //var notification = new Notification
                            //{
                            //    NotificationUID = Guid.NewGuid(),
                            //    NotificationText =
                            //        string.Format("{0} sent you an email.", ((User)session.User).Alias),
                            //    Timestamp = msg.Timestamp,
                            //    NotificationPath =
                            //        string.Format(
                            //            "WorldBankBBS.Subboards:WorldBankBBS.Subboards.SubboardPathHandler:ReadMessage|{0}",
                            //            msg.MessageUID),
                            //    UserUID = u.UserUID,
                            //};

                            //mh.Context.Notifications.Add(notification);

                            mh.Context.SaveChanges();
                        }
                    }
                    else
                    {
                        l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_ABORTED);
                        session.Connection.SendData(buffer, 0, l, l);

                    }
                }
            }
            else
            {

                using (var mh = new ModelHelper())
                {
                    mh.BeginNewContext();
                    var builder = new StringBuilder();
                    var originalMessage = mh.Context.Messages.FirstOrDefault(x => x.MessageUID == uid);

                    var wrapLength = (int) session["ScreenWidth"];

                    var who = session.StripString(originalMessage.User.Alias + ">");

                    var lines = session.StripString(originalMessage.MessageBody).Split(new[] {'\n'});

                    for(int li = 0; li < lines.Length; ++li)
                    {
                        var currentLine = who;
                        var line = lines[li];

                        if (line.Trim().Length > 0 && li < lines.Length - 1)
                        {
                            foreach (var word in line.Split(new[] {' ', '\n', '\r', '\t'}))
                            {
                                if (word.Trim().Length > 0)
                                {
                                    if (currentLine.Length + word.Length < wrapLength - 1)
                                    {
                                        currentLine += " " + word;
                                    }
                                    else
                                    {
                                        builder.AppendLine(currentLine);
                                        currentLine = who + " " + word;
                                    }
                                }
                            }
                            if (currentLine.Trim() != who.Trim())
                            {
                                builder.AppendLine(currentLine);
                            }
                        }
                    }

                    builder.AppendLine();

                    var te = new TextEditor();

                    string stripped = builder.ToString();

                    //switch (session.Encoding)
                    //{
                    //    case "PETSCII":
                    //        buffer = new Petscii().GetBytes(stripped);
                    //        break;

                    //    default:
                    //        buffer = new ASCIIEncoding().GetBytes(stripped);
                    //        break;
                    //}

                    // l = translator.StringToBytes(buffer, stripped);
                    buffer = new ASCIIEncoding().GetBytes(stripped);

                    te.LoadFromBuffer(buffer, 0, buffer.Length);
                    var replyTo = mh.Context.Messages.FirstOrDefault(r => r.MessageUID == uid);

                    if (te.Initialize(session,
                        new TextEditor.Field<string>(0, 0)
                        {
                            Format = "0:-" + (sw/2 - 5),
                            LabelText = "{PURPLE}To{WHITE}:{CYAN}",
                            Value = (replyTo.User.Alias ?? replyTo.User.UserName)
                        },
                        new TextEditor.Field<DateTime>(sw/2, 0)
                        {
                            Format = "0:g",
                            LabelText = "{YELLOW}",
                            Value = timestamp.ToLocalTime()
                        },
                        new TextEditor.Field<string>(0, 2)
                        {
                            Format = "0:-" + (sw - 10),
                            LabelText = "{PURPLE}Subject{WHITE}:{CYAN}",
                            Value =
                                "RE: " +
                                (!replyTo.Subject.StartsWith("RE: ") ? "RE: " + replyTo.Subject : replyTo.Subject),
                        },
                        new TextEditor.Field<string>(0, 1)
                        {
                            Format = "0:-" + (sw - 1),
                            LabelText = "{PURPLE}Thread{WHITE}:{CYAN}",
                            Value = Data.Thread.GetFromThreadUID((Guid) session["CurrentThreadUID"]).ThreadName,
                        },
                        3, 1,
                        new TextEditor.Field<string>(0, (int) session["ScreenHeight"] - 1)
                        {
                            Format = "0:-" + (sw - 1),
                            LabelText =
                                session.Encoding == "PETSCII"
                                    ? "{WHITE}. on blank line for command menu"
                                    : "{WHITE}^{YELLOW}A {WHITE}- {CYAN}Abort{WHITE}, ^{YELLOW}S {WHITE}- {CYAN}Save{WHITE}, ^{YELLOW}Z {WHITE}- {CYAN}Undo{WHITE}, ^{YELLOW}R {WHITE}- {CYAN}Redraw{WHITE}",
                            Value = (replyTo.User.Alias ?? replyTo.User.UserName)
                        }
                        ))
                    {
                        l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_POSTED);
                        session.Connection.SendData(buffer, 0, l, l);

                        var msg = new Message
                        {
                            FromUserUID = session.User.UserUID,
                            ToUserUID = replyTo.FromUserUID,
                            MessageUID = Guid.NewGuid(),
                            Timestamp = DateTime.UtcNow,
                            MessageBody = te.Text,
                            Subject = !replyTo.Subject.StartsWith("RE: ") ? "RE: " + replyTo.Subject : replyTo.Subject,
                            ThreadUID = replyTo.ThreadUID,
                        };

                        mh.Context.Messages.Add(msg);
                        var text = string.Format("{0} replied to your post ({1}).", ((User) session.User).Alias,
                            replyTo.Subject);
                        var notification = new Notification
                        {
                            NotificationUID = Guid.NewGuid(),
                            NotificationText = text.Substring(0, Math.Min(text.Length, 80)),
                            Timestamp = msg.Timestamp,
                            NotificationPath =
                                string.Format(
                                    "WorldBankBBS.Subboards:WorldBankBBS.Subboards.SubboardPathHandler:ReadMessage|{0}",
                                    msg.MessageUID),
                            UserUID = replyTo.FromUserUID,
                        };

                        mh.Context.Notifications.Add(notification);

                        mh.Context.SaveChanges();

                    }
                    else
                    {
                        l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_ABORTED);
                        session.Connection.SendData(buffer, 0, l, l);

                    }
                }

            }
        }

        public static void OnReadMessage(object sender, Session session)
        {
            var uid = (Guid)session["SubboardMessageUID"];

            using (var mh = new ModelHelper())
            {
                mh.BeginNewContext();

                var message = mh.Context.Messages.FirstOrDefault(m => m.MessageUID == uid);

                if (message != null && !message.IsDeleted)
                {
                    session["MenuContext"] = new SubboardsContext() { Context = uid.ToString() };

                    var translator = session.Encoding.GetTranslator(session);

                    var buffer = new byte[1024];
                    var l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_HEADER_TOP);
                    session.Connection.SendData(buffer, 0, l, l);

                    l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_HEADER_FROM, message.User.Alias);
                    session.Connection.SendData(buffer, 0, l, l);

                    l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_HEADER_DATE,
                        message.Timestamp.ToLocalTime().ToString("yyyy-MM-dd hh:mm tt"));
                    session.Connection.SendData(buffer, 0, l, l);

                    l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_HEADER_SUBJECT, message.Subject);
                    session.Connection.SendData(buffer, 0, l, l);

                    l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_HEADER_BOTTOM);
                    session.Connection.SendData(buffer, 0, l, l);

                    l = translator.StringToBytes(buffer, "{CRLF}{LGRAY}{{0}", message.MessageBody);
                    var bb = buffer.WrapText(0, l, session.Encoding, (int)session["ScreenWidth"]);
                    var pages = bb.Paginate(0, bb.Length, 20, session.Encoding);
                    for (int b = 0; b < pages.Count; ++b)
                    {
                        session.Connection.SendData(pages[b], 0, pages[b].Length, 1);
                        if (b != pages.Count - 1)
                            session.InvokePause(session.Encoding);
                    }

                    mh.Context.SaveChanges();

                    Message.MarkReadForUser(uid, session.User.UserUID);
                }
                else
                {
                    var translator = session.Encoding.GetTranslator(session);
                    var buffer = new byte[1024];
                    var l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_NOT_FOUND);
                    session.Connection.SendData(buffer, 0, l, l);
                }
            }
        }

        public static void OnPreDeleteMessage(object sender, Session session)
        {
            var translator = session.Encoding.GetTranslator(session);

            var buffer = new byte[1024];
            var l = 0;

            l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_PRE_DELETE);
            session.Connection.SendData(buffer, 0, l, l);
        }

        public static void OnPostDeleteMessage(object sender, Session session)
        {
            var translator = session.Encoding.GetTranslator(session);

            var buffer = new byte[1024];
            var l = 0;

            l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_POST_DELETE);
            session.Connection.SendData(buffer, 0, l, l);
        }

        public static void OnDeleteMessage(object sender, Session session)
        {
            var uid = (Guid)session["CurrentMessageUID"];

            using (var mh = new ModelHelper())
            {
                mh.BeginNewContext();

                var email = mh.Context.Messages.FirstOrDefault(m => m.MessageUID == uid);

                if (email != null)
                {
                    email.IsDeleted = true;

                    mh.Context.SaveChanges();
                }
            }
        }

        public static void OnEnterSubboard(object sender, Session session)
        {
            using (var mh = new ModelHelper())
            {
                mh.BeginNewContext();

                var thread =
                    mh.Context.Threads.ToList().OrderBy(x => x.ThreadName).FirstOrDefault(x => x.SubboardUID == (Guid)session["CurrentSubboardUID"]);

                if (thread != null)
                {
                    session["CurrentThreadUID"] = thread.ThreadUID;
                }
                else
                {
                    session["CurrentThreadUID"] = Guid.Empty;
                }
            }

        }

        public static void OnChangeThread(object sender, Session session)
        {
            // Do Nothing
        }

        public static void OnReadNextMessage(object sender, Session session)
        {
            using (var mh = new ModelHelper())
            {
                mh.BeginNewContext();

                var messages = ListMessages(session, false, false);

                var tu =
                    mh.Context.ThreadUsers.ToList().FirstOrDefault(
                        x => x.ThreadUID == (Guid)session["CurrentThreadUID"] && x.UserUID == session.User.UserUID);

                if (tu != null)
                {
                    var displayNext = false;
                    foreach (var msg in messages)
                    {
                        if (displayNext)
                        {
                            BbsDispatcher.GetDispatcher(session)
                            .GetObject<SubboardsEvents>("WorldBankBBS.Subboards.SubboardsEvents").InvokeReadMessage(msg.MessageUID);
                            break;
                        }

                        if (msg.MessageUID == tu.LastMessageReadUID) displayNext = true;
                    }
                }
                else
                {
                    if (messages.Count > 0)
                    {
                        BbsDispatcher.GetDispatcher(session)
                            .GetObject<SubboardsEvents>("WorldBankBBS.Subboards.SubboardsEvents").InvokeReadMessage(messages[0].MessageUID);

                    }
                }
            }
        }

        public static void OnNewScan(object sender, Session session)
        {
            var originalThread = (Guid)session["CurrentThreadUID"];
            var originalSubboard = (Guid)session["CurrentSubboardUID"];
            using (var mh = new ModelHelper())
            {
                mh.BeginNewContext();

                foreach (var sig in mh.Context.Sigs.Where(s => !s.IsDeleted))
                {
                    foreach (var sub in sig.Subboards.Where(sb => !sb.IsDeleted))
                    {
                        foreach (var thread in sub.Threads.Where(t => !t.IsDeleted))
                        {
                            foreach (
                                var message in thread.Messages.Where(x => !x.IsDeleted).OrderBy(x => x.Timestamp).ToList())
                            {
                                var messageUser = message.MessageUsers.FirstOrDefault(
                                    mu => mu.UserUID == session.User.UserUID);

                                if (messageUser == null)
                                {
                                    messageUser =
                                        new MessageUser
                                        {
                                            MessageUID = message.MessageUID,
                                            UserUID = session.User.UserUID
                                        };
                                    mh.Context.MessageUsers.Add(messageUser);
                                    mh.Context.SaveChanges();
                                }

                                var isRead = messageUser.IsRead;

                                if (!isRead)
                                {
                                    session["CurrentSubboardUID"] = sub.SubboardUID;
                                    session["CurrentThreadUID"] = thread.ThreadUID;
                                    session["SubboardMessageUID"] = message.MessageUID;

                                    OnReadMessage(sender, session);

                                    if (!NewScanOptions(message, session)) return;
                                }
                            }
                        }
                    }
                }
            }
        }

        private static bool NewScanOptions(Message message, Session session)
        {
            InputHandler inputHandler = new InputHandler();

            var translator = session.Encoding.GetTranslator(session);
            var buffer = new byte[1024];
            var l = translator.StringToBytes(buffer, SubboardStrings.SUBBOARD_READ_NEW_PROMPT);
            session.Connection.SendData(buffer, 0, l, l);

            while (true)
            {
                TextInput -= inputHandler.OnTextInput;
                TextInput += inputHandler.OnTextInput;

                var choice = TextInput(session, translator, session.Connection, 1, false);

                TextInput -= inputHandler.OnTextInput;

                switch (choice.Trim().ToLower())
                {
                    case "":
                        return true;

                    case "q":
                        return false;

                    case "r":
                        session["ReplyToSubboardMessageUID"] = message.MessageUID;
                        OnCreateMessage(session, session);
                        break;
                }
            }
        }
    }
}
